package cn.lg.soar.system.api.service;

import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.system.api.model.DictItemVo;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 字典接口
 * @author luguoxiang
 * @date 2021-08-11
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface IDictApi {

    /**
     * 根据字典类型获取数据字典list
     * @param type 字典类型
     * @return
     */
    List<DictItemVo> listByType(String type);

    /**
     * 批量获取
     * @param types 字典类型
     * @return
     */
    Map<String, List<DictItemVo>> listBatch(Collection<String> types);

    /**
     * 获取数据字典
     * @param type 字典类型
     * @param value 字典值
     * @return
     */
    DictItemVo getDict(String type, Integer value);

    /**
     * 获取字典标签名
     * @param type 字典类型
     * @param value 字典值
     * @return
     */
    String getLabel(String type, Integer value);

    /**
     * 批量获取
     * @param types 字典类型
     * @return
     */
    default Map<String, List<DictItemVo>> listBatch(String ...types) {
        AssertUtil.notEmpty(types, "types must not be empty");
        return listBatch(Arrays.asList(types));
    }

    /**
     * 根据字典类型获取数据字典map
     * @param type 字典类型
     * @return
     */
    default Map<Integer, DictItemVo> mapByType(String type) {
        List<DictItemVo> list = listByType(type);
        return list.stream().collect(Collectors.toMap(DictItemVo::getValue, x -> x));
    }

    /**
     * 根据字典类型获取数据字典map
     * @param type 字典类型
     * @return
     */
    default Map<Integer, String> labelMapByType(String type) {
        List<DictItemVo> list = listByType(type);
        return list.stream().collect(Collectors.toMap(DictItemVo::getValue, DictItemVo::getLabel));
    }

    /**
     * 根据字典类型获取数据字典map
     * @param types 字典类型
     * @return
     */
    default Map<String, Map<Integer, DictItemVo>> mapBatch(Collection<String> types) {
        Map<String, List<DictItemVo>> batch = listBatch(types);
        Map<String, Map<Integer, DictItemVo>> res = new HashMap<>();
        batch.forEach((k, list) -> {
            res.put(k, list.stream().collect(Collectors.toMap(DictItemVo::getValue, x -> x)));
        });
        return res;
    }

    /**
     * 根据字典类型获取数据字典map
     * @param types 字典类型
     * @return
     */
    default Map<String, Map<Integer, DictItemVo>> mapBatch(String ...types) {
        AssertUtil.notEmpty(types, "types must not be empty");
        return mapBatch(Arrays.asList(types));
    }

    /**
     * 根据字典类型获取数据字典map
     * @param types 字典类型
     * @return
     */
    default Map<String, Map<Integer, String>> labelMapBatch(Collection<String> types) {
        Map<String, List<DictItemVo>> batch = listBatch(types);
        Map<String, Map<Integer, String>> res = new HashMap<>();
        batch.forEach((k, list) -> {
            res.put(k, list.stream().collect(Collectors.toMap(DictItemVo::getValue, DictItemVo::getLabel)));
        });
        return res;
    }

    /**
     * 根据字典类型获取数据字典map
     * @param types 字典类型
     * @return
     */
    default Map<String, Map<Integer, String>> labelMapBatch(String ...types) {
        AssertUtil.notEmpty(types, "types must not be empty");
        return labelMapBatch(Arrays.asList(types));
    }

    /**
     * 获取数据字典
     * @param type 字典类型
     * @param values 字典值
     * @return
     */
    default Stream<DictItemVo> getDicts(String type, Collection<Integer> values) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        Map<Integer, DictItemVo> map = mapByType(type);
        return values.stream().map(map::get);
    }

    /**
     * 获取数据字典
     * @param type 字典类型
     * @param values 字典值
     * @return
     */
    default Stream<DictItemVo> getDicts(String type, Integer...values) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        Map<Integer, DictItemVo> map = mapByType(type);
        return Arrays.stream(values).map(map::get);
    }

    /**
     * 获取数据字典
     * @param type 字典类型
     * @param values 字典值
     * @param joiner 值连接符
     * @return
     */
    default Stream<DictItemVo> getDicts(String type, String values, String joiner) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        String[] split = values.split(joiner);
        Map<Integer, DictItemVo> map = mapByType(type);
        return Arrays.stream(split).map(x -> map.get(Integer.parseInt(x)));
    }

    /**
     * 获取字典标签名
     * @param type 字典类型
     * @param values 字典值
     * @return
     */
    default Stream<String> getLabels(String type, Collection<Integer> values) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        Map<Integer, String> map = labelMapByType(type);
        return values.stream().map(map::get);
    }

    /**
     * 获取字典标签名
     * @param type 字典类型
     * @param values 字典值
     * @return
     */
    default Stream<String> getLabels(String type, Integer...values) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        Map<Integer, String> map = labelMapByType(type);
        return Arrays.stream(values).map(map::get);
    }

    /**
     * 获取字典标签名
     * @param type 字典类型
     * @param values 字典值
     * @param joiner 值连接符
     * @return
     */
    default Stream<String> getLabels(String type, String values, String joiner) {
        if (DataUtil.isEmpty(values)) {
            return Stream.empty();
        }
        String[] split = values.split(joiner);
        Map<Integer, String> map = labelMapByType(type);
        return Arrays.stream(split).map(x -> map.get(Integer.parseInt(x)));
    }

}
